#include <stdio.h>
#include <stdlib.h>
#include "MQTTClient.h"
#include "thirdparty/log.h"
#include "app/app_mqtt.h"
#include <assert.h>

static MQTTClient client;                                                           // 创建MQTT客户端句柄
static MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; // 初始化连接选项
static MQTTClient_message pubmsg = MQTTClient_message_initializer;                  // 初始化消息结构体
static MQTTClient_deliveryToken token;                                              // 用于跟踪消息交付状态的令牌
// 声明一个函数指针接受 register——receive注册的函数指针
static int (*reve)(char *, int); //成功返回0  失败返回-1

/**
 * 发送成功的回调函数
 * 成功返回0  失败-1
 */
void delivered(void *context, MQTTClient_deliveryToken dt)
{
    assert(context == NULL);
     log_trace("Message with token value %d delivery confirmed\n", dt);
}

/**
 * 接受成功的回调函数
 * 成功返回1  失败0
 */
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    assert(context == NULL);
     log_trace("Message arrived: topic %s, message %s", topicName, message->payload);
    //执行被注册的回调函数
    int result =  reve(message->payload,message->payloadlen);
    return result == 0 ? 1 : 0;
}

/**
 * 断开连接的回调函数
 */
void connlost(void *context, char *cause)
{
    assert(context == NULL);
    log_warn("Connection lost because of %s", cause);
}


/**
 * 初始化客户端
 * 成功返回0  失败-1
 */
int app_mqtt_init(void)
{
    //创建一个客户端
    if(MQTTClient_create(&client, ADDRESS, CLIENTID,MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS)
    {
        //创建失败
        log_error("client create fail");
        goto MQTT_CREATE_FAIL;
    }

    //注册设置回调函数  同时创建了一个线程 当接受到消息是有客户端创建的线程执行回调函数不是主线程执行
    if(MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered) != MQTTCLIENT_SUCCESS)
    {
        log_error("set callbake fail");
        goto MQTT_CONNECT_FAIL;
    }

    //设置连接参数
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    //连接服务器
    if(MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS)
    {
        //连接失败
        log_error("client connect fail");
        goto MQTT_CONNECT_FAIL;
    }

    //订阅主题
    if(MQTTClient_subscribe(client, PULL_TOPIC, QOS) != MQTTCLIENT_SUCCESS)
    {
        log_error("client subscribe fail");
        goto MQTT_SUBSCRIBE_FAIL;
    }
    return 0;

MQTT_SUBSCRIBE_FAIL:
    MQTTClient_disconnect(client, 10000);
MQTT_CONNECT_FAIL:
    MQTTClient_destroy(&client);  //删除客户端
MQTT_CREATE_FAIL:
    return -1;
}

/**
 * 向服务器发送数据
 * 成功返回0  失败-1
 */
int app_mqtt_send(char *payload, int payload_len)
{
    //设置要发送的参数
    pubmsg.payload = payload;  
    pubmsg.payloadlen = payload_len;
    pubmsg.qos = QOS;
    pubmsg.retained = 0; 
    int result =  MQTTClient_publishMessage(client, PUSH_TOPIC, &pubmsg, &token);
    if(result == MQTTCLIENT_SUCCESS)
    {
        //发送成功
        log_trace("Message with delivery token %d delivered", token);
        return 0;
    }
    else
    {
        log_warn("Message with delivery token %d failed", token);
        return -1;
    }
}
/**
 * 注册接受数据的函数指针
 */
int app_mqtt_registerReceive(int (*reve_callbake)(char *payload, int payload_len))
{
    //注册回调函数
    reve = reve_callbake;
    return 0;
}

/**
 * 删除客户端
 */
void app_mqtt_close(void)
{
     // 尝试断开连接
    MQTTClient_disconnect(client, 10000);
 
    // 销毁客户端实例
    MQTTClient_destroy(&client);
}